package kgame5.pbe.atlantic.comp {
import kgame5.k3d.core.obj3d.spacial.SpacialVO;
import kgame5.pbe.atlantic.event.FSMEvent;
import kgame5.pbe.atlantic.event.GameCommandEvent;
import kgame5.pbe.atlantic.event.ViewEvent;
import kgame5.pbe.atlantic.vo.EntityMessageVO;
import kgame5.pbe.atlantic.vo.EntityVO;
import kgame5.pbe.engine.PBE;
import kgame5.pbe.engine.entity.EntityComponent;

/**
	 * @author max
	 * 2011-1-14
	 * 一个实体内的控制器，负责viewComp.logicComp通信，对外发送事件，接收外部命令
	 * 注意，接收外部命令通过handleGameCommand(commandName:String,data:Object)来做
	 * 这样不必对暴露接口
	 * 内建支持一些方法
	 * 
	 * viewComp发出输入的事件，logicComp接收输入的事件，进行处理
	 * 
	 * 注意，这个是entity需要与外部交互的时候才用的，entity对外发送命令和接收外部命令用
	 * 如果不需要与外部交互，由viewComp和logicComp即可完成任务
	 * 
	 * 被外部调用的命令用handleToEntityCommand
	 * 通知外部用sendFromEntityCommand
	 * 响应内部事件用onXX
	 * 
	 * ---注意，controllerComp中使用handlerToEntityCommand而不是直接暴露具体函数来执行外部命令，这样做是有原因的
	 * 这样GamePlay中不必关心某个entity有哪些comp，comp有哪些对外方法。
	 * 其实GamePlay本来也不需要关心这些，gamePlay只关心对外发送命令即可
	 */
	public class ControllerComp extends EntityComponent implements IEntityCompFacade{
		
		
		
		public static const NAME:String="ControllerComp";
		
		//快捷方式，收到外部命令切换形态，改变方向，播放动画，这个很有用，entity要具备接受外部命令进而执行
		public static const 
			
			TO_ENTITY_COMMAND_DESTROY:String="TO_ENTITY_COMMAND_DESTROY",//销毁entity
			
			TO_ENTITY_COMMAND_CHANGE_FORM:String="TO_ENTITY_COMMAND_CHANGE_FORM",
			TO_ENTITY_COMMAND_CHANGE_DIR:String="TO_ENTITY_COMMAND_CHANGE_DIR",
			TO_ENTITY_COMMAND_PLAY_ANIM:String="TO_ENTITY_COMMAND_PLAY_ANIM";
		
		protected var entVO:EntityVO;
		protected var spcVO:SpacialVO;
		
		protected var logicComp:FSMBatchComp;
		protected var _viewComp:ViewComp2D;
		
		public function ControllerComp(){
		
		}
		
		//在这里提取各个comp
		//!!严重注意，对需要操控的comp的提取放到这里，比在构造函数里传入要更好，否则需要每个controller都要覆写复杂的构造函数
		override protected function onReset():void{
			var dataComp:DataComp=owner.lookupComponentByName(DataComp.NAME) as DataComp;
			this.entVO=dataComp.entVO;
			this.spcVO = this.entVO.spcVO;
			this.logicComp=owner.lookupComponentByName(FSMBatchComp.NAME) as FSMBatchComp;
			this._viewComp=owner.lookupComponentByName(ViewComp2D.NAME) as ViewComp2D;
		}

		override protected function onAdd():void{
			owner.eventDispatcher.addEventListener(FSMEvent.TYPE, onFSMEvent);
			owner.eventDispatcher.addEventListener(ViewEvent.TYPE, onViewEvent);
			
			//owner.eventDispatcher.addEventListener(EntityMessageEvent.TYPE, onEntityToEntityMessageEvent);//这个暂时不处理
			
			//gameCommand会发送到GamePlay
			//owner.eventDispatcher.addEventListener(GameCommandEvent.TYPE, onGameCommandEvent);
		}
		
		override protected function onRemove():void{
			owner.eventDispatcher.removeEventListener(FSMEvent.TYPE, onFSMEvent);
			owner.eventDispatcher.removeEventListener(ViewEvent.TYPE, onViewEvent);
			
			//owner.eventDispatcher.removeEventListener(EntityMessageEvent.TYPE, onEntityToEntityMessageEvent);//这个暂时不处理
			
			//gameCommand会发送到GamePlay
			//owner.eventDispatcher.addEventListener(GameCommandEvent.TYPE, onGameCommandEvent);
		}
		
		
		
		//#对外提供，也是供子类继承用,处理游戏命令
		//这个是有用的，有些交互不一定来自引擎内部，比如有人用手点击了水族箱
		//处理发送到entity的command,很有用
		//~~用handler来处理外部命令而不是对外直接暴露命令接口，这样当gamePlay里想执行命令式，只是executeEntityCommand即可，
		//否则则需要(PBE.lookupCompByName(entityID,compName) as XXXContorller).xxxFunc(xxx);
		public function handleToEntityCommand(commandName:String,data:Object=null):void{
			switch(commandName){
				case TO_ENTITY_COMMAND_DESTROY:
				owner.destroy();//收到外部命令销毁
				break;
				case TO_ENTITY_COMMAND_CHANGE_FORM:
				var formID:int=data as int;
				_viewComp.changeForm(formID);
				break;
				case TO_ENTITY_COMMAND_CHANGE_DIR:
				var dir:int=data as int;
				_viewComp.changeDir(dir);
				break;
				case TO_ENTITY_COMMAND_PLAY_ANIM:
				var animID:String=data as String;
				_viewComp.playAnim(animID);
				break;
			}
		}
		
		

		//注意这个和ControllerComp中的command是相互独立的,原因是有的entity不需要controller
		public function sendFromEntityCommand(commandName : String,data : Object = null) : void {
			owner.eventDispatcher.dispatchEvent(new GameCommandEvent(commandName, data));
		}
		
		protected function onFSMEvent(e:FSMEvent):void{
			switch(e.name){
				case FSMEvent.NAME_CHANGE_DIR:
				var dir:int=e.data as int;
				_viewComp.changeDir(dir);
				break;
				case FSMEvent.NAME_PLAY_ANIM:
				var animID:String=e.data as String;
				_viewComp.playAnim(animID);
				break;
				case FSMEvent.NAME_CHANGE_FORM:
				var formID:int=e.data as int;
				_viewComp.changeForm(formID);
				break;
			}
		}
		
		protected function onViewEvent(e:ViewEvent):void{
			switch(e.name){
				case ViewEvent.NAME_CLICK:
				if(logicComp){
					logicComp.click(e.data.x,e.data.y);
				}
				onViewCompClick(e.data.x,e.data.y);
				break;
				case ViewEvent.NAME_EOF:
				if(logicComp){
					logicComp.endOfFrame(e.data as String);
				}
				break;
				
				case ViewEvent.NAME_ROLL_OVER:
				if(logicComp){
					logicComp.rollOver();
				}
				this.onViewCompRollOver();
				break;
				case ViewEvent.NAME_ROLL_OUT:
				if(logicComp){
					logicComp.rollOut();
				}
				this.onViewCompRollOut();
				break;
				case ViewEvent.NAME_ASSET_OK:
				this.onViewCompAssetOK();
				break;
				case ViewEvent.NAME_SIZE_CHANGED:
				this.onViewCompSizeChanged(e.data.x, e.data.y,e.data.width,e.data.height);
				break;
			}
		}
		
		//#资源加载完毕
		protected function onViewCompAssetOK():void{
			
		}
		//#被点击
		protected function onViewCompClick(x:int,y:int):void{
			
		}
		//#
		protected function onViewCompSizeChanged(x:int,y:int,w:int,h:int):void{
			
		}
		//#
		protected function onViewCompRollOver():void{
			
		}
		//#
		protected function onViewCompRollOut():void{
			
		}
		
//		//============收到某comp的命令，需要发送entityToEntity的命令
//		protected function onEntityToEntityMessageEvent(e:EntityMessageEvent):void{
//			
//		}
//		
//		//发送entity到entity的消息
//		protected function sendEntityToEntityMessage(mvo:EntityMessageVO):void{
//			var dict:Dictionary;
//			switch(mvo.scope){
//				case EntityMessageVO.SCOPE_ALL:
//					dict=PBE.senseWorld.getVOList();
//					break;
//				case EntityMessageVO.SCOPE_BY_CATEID:
//					dict=PBE.senseWorld.get
//					break;
//				case EntityMessageVO.SCOPE_BY_TYPEID:
//					break;
//				case EntityMessageVO.SCOPE_SOMEONE:
//					break;
//			}
//		}
		
		//=================
		//-entityToEntityMessage的消息的事件接收-
		public function handleEntityToEntityMessage(mvo:EntityMessageVO):void{
			
		}
		
		//==============实体间发消息，比如一条鱼通知另一条鱼来吃食======
		public function sendEntityToEntityMessage(msgName : String,toID : String,scope : int=1,data : *=null) : void {
			//T.p("sendEntityToEntityMessage",msgName,toID);
			var mvo : EntityMessageVO = new EntityMessageVO(msgName, data, entVO, scope,toID);
			PBE.senseWorld.sendEntityToEntityMessage(mvo);
			//eventDispatcher.dispatchEvent(new EntityMessageEvent(EntityMessageEvent.TYPE, mvo));
		}
	}//end of class
}
